package com.joizhang.seckill.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.joizhang.seckill.api.redis.UserKey;
import com.joizhang.seckill.api.service.UserService;
import com.joizhang.seckill.api.service.exception.ServiceException;
import com.joizhang.seckill.api.vo.LoginVo;
import com.joizhang.seckill.api.vo.UserVo;
import com.joizhang.seckill.mapper.UserMapper;
import com.joizhang.seckill.model.User;
import com.joizhang.seckill.redis.RedisService;
import com.joizhang.seckill.utils.MD5Util;
import com.joizhang.seckill.utils.ServiceCodeMsg;
import com.joizhang.seckill.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Objects;

@DubboService
@Service
public class UserServiceImpl implements UserService {

    final UserMapper userMapper;

    final RedisService redisService;

    @Autowired
    public UserServiceImpl(UserMapper userMapper, RedisService redisService) {
        this.userMapper = userMapper;
        this.redisService = redisService;
    }

    @Override
    public void userSignUp(UserVo userVo) {
        Objects.requireNonNull(userVo);
        User user = userMapper.getUserByPhoneNumber(userVo.getPhoneNumber());
        if (!Objects.isNull(user)) {
            throw new ServiceException(ServiceCodeMsg.MOBILE_ALREADY_EXIST);
        }
        user = userMapper.getUserByUsername(userVo.getUsername());
        if (!Objects.isNull(user)) {
            throw new ServiceException(ServiceCodeMsg.USERNAME_ALREADY_EXIST);
        }
        user = new User();
        BeanUtils.copyProperties(userVo, user);
        String salt = MD5Util.getSalt();
        String password = MD5Util.inputPassToDbPass(userVo.getPassword(), salt);
        user.setSalt(salt);
        user.setPassword(password);
        user.setRegisterDate(LocalDateTime.now());
        user.setLoginCount(0);
        userMapper.insertUser(user);
    }

    @Override
    public String userSignIn(LoginVo loginVo) {
        if (Objects.isNull(loginVo) || Objects.isNull(loginVo.getCredential())) {
            throw new ServiceException(ServiceCodeMsg.MOBILE_EMPTY);
        }
        if (Objects.isNull(loginVo.getPassword())) {
            throw new ServiceException(ServiceCodeMsg.PASSWORD_EMPTY);
        }
        String credential = loginVo.getCredential();
        String formPass = loginVo.getPassword();
        // 判断手机号是否存在
        User user = userMapper.getUserByCredential(credential);
        if (Objects.isNull(user)) {
            throw new ServiceException(ServiceCodeMsg.ACCOUNT_NOT_EXIST);
        }
        //验证密码
        String dbPass = user.getPassword();
        String saltDB = user.getSalt();
        String calcPass = MD5Util.formPassToDBPass(formPass, saltDB);
        if (!calcPass.equals(dbPass)) {
            throw new ServiceException(ServiceCodeMsg.PASSWORD_ERROR);
        }
        // 缓存用户数据
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(userVo));
        redisService.setHashAll(UserKey.USER_ID, String.valueOf(user.getId()), jsonObject);

        // 生成唯一id作为token
        String token = UUIDUtil.uuid();
        redisService.set(UserKey.TOKEN, token, user.getId());
        return token;
    }

    @Override
    public UserVo getUserById(Long id) {
        UserVo userVo;
        //对象缓存
        userVo = (UserVo) redisService.getHash(UserKey.USER_ID, "", String.valueOf(id));
        if (Objects.isNull(userVo) && !Objects.isNull(id)) {
            //取数据库
            User user = userMapper.getUserById(id);
            //再存入缓存
            if (!Objects.isNull(user)) {
                userVo = new UserVo();
                BeanUtils.copyProperties(user, userVo);
                redisService.setHash(UserKey.USER_ID, "", String.valueOf(id), userVo);
            }
        }
        return userVo;
    }

    @Override
    public UserVo getUserByTokenFromCache(String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        Object obj = redisService.get(UserKey.TOKEN, token);
        if (Objects.isNull(obj)) {
            return null;
        }
        redisService.set(UserKey.TOKEN, token, obj);
        JSONObject jsonObject = redisService.getHashAll(UserKey.USER_ID, obj.toString());
        if (jsonObject.isEmpty()) {
            return null;
        }
        return JSONObject.toJavaObject(jsonObject, UserVo.class);
    }

    @Override
    public boolean updatePassword(String token, Long id, String formPass) {
        // 取user
        User user = userMapper.getUserById(id);
        if (Objects.isNull(user)) {
            throw new ServiceException(ServiceCodeMsg.MOBILE_NOT_EXIST);
        }
        // 更新数据库
        User toBeUpdate = new User();
        toBeUpdate.setId(id);
        toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
        userMapper.update(toBeUpdate);
        // 更新缓存：先删除再插入
        redisService.delete(UserKey.USER_ID, "" + id);
        user.setPassword(toBeUpdate.getPassword());
        redisService.set(UserKey.TOKEN, token, user.getId());
        return true;
    }

    public void doubleInsert() {
    }
}
